package tp1POO.Persistencia;


import java.util.List;
import java.util.Vector;

import tp1POO.Modelo.Cliente;
import tp1POO.Modelo.Funcionario;
import tp1POO.Modelo.Locacao;
import tp1POO.Modelo.Motorista;
import tp1POO.Modelo.ObjetoPOO;
import tp1POO.Modelo.Tipo;
import tp1POO.Modelo.Veiculo;


public class Pesquisa {

	/** Pesquisa por um cliente de nome especificado pelo prâmetro.
	 *
	 * @param nome - Nome do cliente procurado
	 * @return Cliente - cliente de nome igual ao parâmetro. Retorna NULL se o cliente não existir.
	 */
	public  static Cliente ObterClienteNome(String nome) {
		Cliente cli = new Cliente();
		Vector<ObjetoPOO> cliente = GerenciadorObjetos.obterInstancia().obterObjs(cli);
		Cliente clienteProcurado;
		int i;

		if (cliente.isEmpty()) {
			//System.out.print("ERRO");
			return null;
		} else {
			for (i = 0; i < cliente.size(); i++) {
				clienteProcurado = (Cliente)cliente.get(i);
				if (clienteProcurado.getNome().compareToIgnoreCase(nome) == 0) {
					return clienteProcurado;
				}
			}
		}
		return null;
	}

	/** Pesquisa por um cliente de CPF especificado pelo prâmetro.
	 *
	 * @param cpf - CPF do cliente procurado
	 * @return Cliente - cliente de CPF igual ao parâmetro. Retorna NULL se o cliente não existir.
	 */
	public static Cliente ObterClienteCpf(String cpf) {
		Cliente cli = new Cliente();
		Vector<ObjetoPOO> cliente = GerenciadorObjetos.obterInstancia().obterObjs(cli);
		Cliente clienteProcurado = null;
		int i;

		if (cliente.isEmpty()) {
			return null;
		} else {
			for (i = 0; i < cliente.size(); i++) {
				clienteProcurado = (Cliente)cliente.get(i);
				if (clienteProcurado.getCpf().compareToIgnoreCase(cpf) == 0) {
					return clienteProcurado;
				}
			}
		}
		return null;
	}

	/** Pesquisa por uma locação, dados o nome do cliente, a placa do veículo alugado e a data de saída
	 *  da locação.
	 * @param parNome - Nome do cliente que realizou a locação procurada.
	 * @param parPlaca - Placa do veículo alugado.
	 * @param parData - Data em que a locação foi realizada(no formato dd/mm/aa).
	 * @return Locacao - Locação procurada.
	 */
	public static Locacao ObterLocacao(String parNome, String parPlaca, String parData) {
		Locacao loc = new Locacao(new Veiculo(""), new Cliente());
		Vector<ObjetoPOO> locacoes = GerenciadorObjetos.obterInstancia().obterObjs(loc);
		Locacao locacaoProcurada = null;
		int i;

		for (i = 0; i < locacoes.size(); i++) {
			Locacao tmp = (Locacao)locacoes.get(i);
			if (tmp.getLocador().getNome().compareToIgnoreCase(parNome) == 0 &&
					tmp.getDataSaida().compareToIgnoreCase(parData) == 0 &&
					tmp.getVeiculo().getPlaca().compareToIgnoreCase(parPlaca) == 0)
			{locacaoProcurada = tmp; break;}
		}
		return locacaoProcurada;
	}

	/**
	 * Pesquisa pela locação do veículo de placa igual ao parâmetro.
	 * @param placa - Placa do veículo alugado.
	 * @return Locacao - Locação do veículo.
	 */
	public static Locacao ObterLocacaoVeiculo(String placa) {
		Veiculo veiculo = new Veiculo("");
		Cliente cli = new Cliente();
		Locacao loc = new Locacao(veiculo, cli);
		Vector<ObjetoPOO> locacoes = GerenciadorObjetos.obterInstancia().obterObjs(loc);
		Locacao locacaoProcurada = null;
		int i;

		if (locacoes.isEmpty()) {
			return null;
		} else {
			for (i = 0; i < locacoes.size(); i++) {
				locacaoProcurada = (Locacao)locacoes.get(i);
				if (locacaoProcurada.getVeiculo().getPlaca().compareToIgnoreCase(placa) == 0) {
					return locacaoProcurada;
				}
			}
		}
		return null;
	}

	/**
	 * Pesquisa pelo veículo cuja plca é igual ao parâmetro passado.
	 * @param placa - Placa do veículo procurado.
	 * @return Veiculo - veículo procurado.
	 */
	public static Veiculo ObterVeiculo(String placa) {
		Veiculo v = new Veiculo("");
		Vector<ObjetoPOO> veiculo = GerenciadorObjetos.obterInstancia().obterObjs(v);
		Veiculo veiculoProcurado = null;
		int i;

		if (veiculo.isEmpty()) {
			return null;
		} else {
			for (i = 0; i < veiculo.size(); i++) {
				veiculoProcurado = (Veiculo)veiculo.get(i);
				if (veiculoProcurado.getPlaca().compareToIgnoreCase(placa) == 0) {
					return veiculoProcurado;
				}
			}
		}
		return null;
	}

	/**
	 * Pesquisa pelo motorista de CNH igual a String passada como parâmetro.
	 * @param cnh - CNH do motorista procurado.
	 * @return Motorista - mototista procurado.
	 */
	public static Motorista ObterMotoristaCnh(String cnh) {
		Motorista motoristaProcurado = null;
		Motorista mot = new Motorista("");
		Vector<ObjetoPOO> motorista = GerenciadorObjetos.obterInstancia().obterObjs(mot);
		int i;

		if (motorista.isEmpty()) {
			return null;
		} else {
			for (i = 0; i < motorista.size(); i++) {
				motoristaProcurado = (Motorista)motorista.get(i);
				if (motoristaProcurado.getCNH().compareToIgnoreCase(cnh) == 0) {
					return motoristaProcurado;
				}
			}
		}
		return null;
	}

	/**
	 * Pesquisa pelo motorista de nome igual a String passada como parâmetro.
	 * @param nome - Nome do motorista procurado.
	 * @return Motorista - mototista procurado.
	 */
	public static Motorista ObterMotoristaNome(String nome) {
		Motorista mot = new Motorista("");
		Vector<ObjetoPOO> motorista = GerenciadorObjetos.obterInstancia().obterObjs(mot);
		Motorista motoristaProcurado;
		int i;

		if (motorista.isEmpty()) {
			return null;
		} else {
			for (i = 0; i < motorista.size(); i++) {
				motoristaProcurado = (Motorista)motorista.get(i);
				if (motoristaProcurado.getNome().compareToIgnoreCase(nome) == 0) {
					return motoristaProcurado;
				}
			}
		}
		return null;
	}

	/**
	 * Pesquisa pelo motorista de CPF igual a String passada como parâmetro.
	 * @param cpf - CPF do motorista procurado.
	 * @return Motorista - mototista procurado.
	 */
	public static Motorista ObterMotoristaCpf(String cpf) {
		Motorista mot = new Motorista("");
		Vector<ObjetoPOO> motorista = GerenciadorObjetos.obterInstancia().obterObjs(mot);
		Motorista motoristaProcurado;
		int i;

		if (motorista.isEmpty()) {
			return null;
		} else {
			for (i = 0; i < motorista.size(); i++) {
				motoristaProcurado = (Motorista)motorista.get(i);
				if (motoristaProcurado.getCpf().compareTo(cpf) == 0) {
					return motoristaProcurado;
				}
			}
		}
		return null;
	}

	/**
	 * Pesquisa pelo funcionário de nome igual a String passada como parâmetro.
	 * @param nome - Nome do funcionário procurado.
	 * @return Funcionario - funcionário procurado.
	 */
	public static Funcionario ObterFuncionarioNome(String nome) {
		Funcionario func = new Funcionario(Funcionario.Cargo.Auxiliar);
		Vector<ObjetoPOO> funcionario = GerenciadorObjetos.obterInstancia().obterObjs(func);
		Funcionario funcionarioProcurado;
		int i;

		if (funcionario.isEmpty()) {
			return null;
		} else {
			for (i = 0; i < funcionario.size(); i++) {
				funcionarioProcurado = (Funcionario)funcionario.get(i);
				if (funcionarioProcurado.getNome().compareTo(nome) == 0) {
					return funcionarioProcurado;
				}
			}
		}
		return null;
	}

	/**
	 * Pesquisa pelo funcionário de CPF igual a String passada como parâmetro.
	 * @param cpf - CPF do funcionário procurado.
	 * @return Funcionario - funcionário procurado.
	 */
	public static Funcionario obterFuncionario(String cpf) {
		Funcionario func = new Funcionario(Funcionario.Cargo.Auxiliar);
		Vector<ObjetoPOO> funcionario = GerenciadorObjetos.obterInstancia().obterObjs(func);
		Funcionario funcionarioProcurado;
		int i;

		if (funcionario.isEmpty()) {
			return null;
		} else {
			for (i = 0; i < funcionario.size(); i++) {
				funcionarioProcurado = (Funcionario)funcionario.get(i);
				if (funcionarioProcurado.getCpf().compareTo(cpf) ==0) {
					return funcionarioProcurado;
				}
			}
		}
		return null;
	}

	/**
	 * Pesquisa pelo Tipo de locação de nome igual a String passada como parâmetro.
	 * @param nome - Nome do tipo de locação procurado.
	 * @return Tipo - Tipo de locação procurado.
	 */
	public static Tipo obterTipoLocacao (String nome) {
		Tipo tipo = new Tipo("");
		Vector<ObjetoPOO> tipoVet = GerenciadorObjetos.obterInstancia().obterObjs(tipo);
		if (tipoVet.isEmpty()) {
			return null;
		} else {
			for (int i = 0; i < tipoVet.size(); i++) {
				tipo = (Tipo)tipoVet.get(i);
				if (tipo.getNome().compareTo(nome) ==0) {
					return tipo;
				}
			}
		}
		return null;
	}

	/**
	 * Pesquisa por um cliente de nome igual a String passada como parâmetro e se existir,
	 * é chamado o Gerenciador de Objetos pra remover o cliente.
	 * @param nome - Nome do cliente a ser removido.
	 * @return boolean - <b>True</b> se o cliente for removido com seucesso e <b>False</b> se o cliente
	 * não existir.
	 */
	public static boolean removeCliente(String nome) {

		Cliente buscaCliente;
		buscaCliente = Pesquisa.ObterClienteNome(nome);
		if (buscaCliente == null) {
			return false;
		}

		GerenciadorObjetos.obterInstancia().removerObjeto(buscaCliente);
		Persistencia.obterInstancia().apagar(buscaCliente);
		return true;
	}

	/**
	 * Remove uma locação do banco de dados
	 * @param nome - Nome do cliente que realizou a locação.
	 * @param  placa - Placa do veículo alugado na locação.
	 * @param dataSaida - Data em que a locação foi realizada.
	 * @return boolean - <b>True</b> se locação for removida com seucesso e <b>False</b> se a locação
	 * não existir.
	 */
	public static boolean removeLocacao(String nome, String placa, String dataSaida) {
		Locacao buscaLocacao;
		buscaLocacao = Pesquisa.ObterLocacao(nome, placa, dataSaida);
		if (buscaLocacao == null) {
			return false;
		}
		GerenciadorObjetos.obterInstancia().salvarObj(buscaLocacao);
		return true;
	}

	/**
	 * Pesquisa por um veículo de placa igual a String passada como parâmetro e se existir,
	 * é chamado o Gerenciador de Objetos pra removê-lo.
	 * @param placa - Placa do veículo a ser removido.
	 * @return boolean - <b>True</b> se o veículo for removido com seucesso e <b>False</b> se o veículo
	 * não existir.
	 */
	public static boolean removeVeiculo(String placa) {
		Veiculo buscaVeiculo;
		buscaVeiculo = Pesquisa.ObterVeiculo(placa);
		if (buscaVeiculo == null) {
			return false;
		}

		GerenciadorObjetos.obterInstancia().removerObjeto(buscaVeiculo);
		Persistencia.obterInstancia().apagar(buscaVeiculo);
		return true;
	}

	/**
	 * Pesquisa por um motorista de CNH igual a String passada como parâmetro e se existir,
	 * é chamado o Gerenciador de Objetos pra remover o cliente.
	 * @param CNH - CNH do motorista a ser removido.
	 * @return boolean - <b>True</b> se o motorista for removido com seucesso e <b>False</b> se o motorista
	 * não existir.
	 */
	public static boolean removeMotorista(String CNH) {
		Motorista buscaMotorista;
		buscaMotorista = Pesquisa.ObterMotoristaCnh(CNH);
		if (buscaMotorista == null) {
			return false;
		}
		GerenciadorObjetos.obterInstancia().salvarObj(buscaMotorista);
		return true;
	}

	/**
	 * Pesquisa por um funcionário de CPF igual a String passada como parâmetro e se existir,
	 * é chamado o Gerenciador de Objetos pra remover o cliente.
	 * @param cpf - CPF do funcionário a ser removido.
	 * @return boolean - <b>True</b> se o funcionário for removido com seucesso e <b>False</b> se o funcionário
	 * não existir.
	 */
	public static boolean removeFuncionario(String cpf) {
		Funcionario buscaFuncionario;
		buscaFuncionario = Pesquisa.obterFuncionario(cpf);
		if (buscaFuncionario == null) {
			return false;
		}
		GerenciadorObjetos.obterInstancia().removerObjeto(buscaFuncionario);
		Persistencia.obterInstancia().apagar(buscaFuncionario);
		return true;
	}

	public static void removeTipo (Tipo tipo) {
		GerenciadorObjetos.obterInstancia().removerObjeto(tipo);
		Persistencia.obterInstancia().apagar(tipo);
		return;
	}

	/**
	 * Pesquisa pelos veículos mais alugados, de acordo com o número de locações realizadas com cada veículo.
	 * @return Vector<Veículo> - vetor de veículos ordenados em ordem decrescente em relação ao
	 * ao número de locações de cada veículo.
	 */
	public static Vector<Veiculo> veiculosMaisAlugados () {
		Vector<ObjetoPOO> veiculos = GerenciadorObjetos.obterInstancia().obterObjs(new Veiculo(""));
		int tamanho = veiculos.size(),i=0;
		Vector<Veiculo> veiculosOrdenados = new Vector<Veiculo>();
		int max=0;
		Veiculo x;

		while (!veiculos.isEmpty()) {
			max = 0;
			for (int j=1;j<tamanho;j++){
				if (((Veiculo)veiculos.get(j)).getLocacoes().size()>((Veiculo)veiculos.get(max)).getLocacoes().size()) {
					max=j;
				}
			}
			x = (Veiculo)veiculos.get(max);
			veiculosOrdenados.add(i, x);
			veiculos.removeElementAt(max);
			tamanho--;
			i++;
		}
		return veiculosOrdenados;

	}

	/**
	 * Pesquisa pelos veículos que mais renderam, de acordo com o valor obtido de todas as locações
	 * rendidas pelo veículo.
	 * @return Vector<Veículo> - vetor de veículos ordenados em ordem decrescente em relação ao
	 * ao valor de renda obtido por cada veículo.
	 */
	public static Vector<Veiculo> veiculosMaisRentaveis (){

		Vector<ObjetoPOO> veiculos = GerenciadorObjetos.obterInstancia().obterObjs(new Veiculo(""));
		float soma = 0,max=0;
		Vector<Veiculo> veiculosOrdenados = new Vector<Veiculo>();
		int tamanho = veiculos.size(), indice=0;

		while (!veiculos.isEmpty()) {
			max = 0;
			indice=0;
			for (int j=0; j<tamanho; j++){
				soma = 0;
				//Obtem o valor obtido por cada veiculo
				for (Locacao loc : ((Veiculo)veiculos.get(j)).getLocacoes())
					soma += loc.getValor();
				if (soma > max) {
					max = soma;
					indice = j;
				}                                
			}

			veiculosOrdenados.add((Veiculo)veiculos.remove(indice));
			tamanho--;
		}

		return veiculosOrdenados;
	}

	/**
	 * Pesquisa pelas locações que ainda estão em andamento.
	 * @return Vector<Locacao> - vetor de todas as locações que ainda foram foram fechadas.
	 */
	public static Vector<Locacao> locacoesEmAberto () {
		Vector<ObjetoPOO> locacoes = GerenciadorObjetos.obterInstancia().obterObjs(new Locacao(new Veiculo(""), new Cliente()));
		Vector<Locacao> tmpLocacoes = new Vector<Locacao>();

		for (ObjetoPOO obj : locacoes) {
			Locacao loc = (Locacao)obj;
			if (loc.getValor() == 0) {
				tmpLocacoes.add(loc);
			}
		}
		return tmpLocacoes;
	}

	/**
	 * Pesquisa pelas locações que já foram fechadas.
	 * @return Vector<Locacao> - vetor de todas as locações que já foram fechadas.
	 */
	public static Vector<Locacao> locacoesFechadas () {
		Veiculo v = new Veiculo("");
		Cliente cli = new Cliente();
		Locacao loc = new Locacao(v, cli);
		Vector<ObjetoPOO> locacoes = GerenciadorObjetos.obterInstancia().obterObjs(loc);
		Vector<Locacao> locacoesFechadas = new Vector<Locacao>();

		for (int i=0; i<locacoes.size();i++){
			if (((Locacao) locacoes.get(i)).getValor() != 0){
				locacoesFechadas.add(((Locacao) locacoes.get(i)));
			}
		}
		return locacoesFechadas;

	}

	/**
	 * Pesquisa pelos veículos que pertencem a categoria de nome igual a String passada por parâmetro.
	 * @param nomeTipo - Nome da categoria.
	 * @return Vector<Veículo> - vetor de veículos que pertencem a mesma categoria.
	 */
	public static Vector<Veiculo> veiculosCategoria (String nomeTipo){
		Veiculo v = new Veiculo("");
		Vector<ObjetoPOO> veiculo = GerenciadorObjetos.obterInstancia().obterObjs(v);
		Vector<Veiculo> categoriaIgual = new Vector<Veiculo>();

		for (int i=0; i<veiculo.size();i++){
			v = (Veiculo)veiculo.get(i);
			if (v.getTipoVeiculo().getNome().compareTo(nomeTipo) == 0){
				categoriaIgual.add((Veiculo)veiculo.get(i));
			}
		}
		return categoriaIgual;
	}

	/**
	 * Pesquisa pelos veículos que estão disponíveis para alugar.
	 * @return Vector<Veículo> - vetor de veículos que não possuem locação pendente.
	 */
	public static Vector<Veiculo> veiculosDisponiveis() {
		Veiculo v = new Veiculo("");
		List<Locacao> locacoes;
		Vector<ObjetoPOO> vet = GerenciadorObjetos.obterInstancia().obterObjs(v);
		Vector<Veiculo> veiculos = new Vector<Veiculo>();

		for (int i=0;i<vet.size();i++) {
			locacoes = ((Veiculo)vet.get(i)).getLocacoes();
			if (!locacoes.isEmpty()) {
				if (locacoes.get(locacoes.size()-1).getValor() != 0) {
					veiculos.add((Veiculo)vet.get(i));
				}
			}
			else {
				veiculos.add((Veiculo)vet.get(i));
			}
		}
		return veiculos;
	}




        public static Funcionario funcionarioLogin (String login) {
            Vector<ObjetoPOO> vet = GerenciadorObjetos.obterInstancia().obterObjs(new Funcionario(Funcionario.Cargo.Administrador));
            Funcionario func;
            for (int i=0;i<vet.size();i++) {
                func = (Funcionario)vet.get(i);
                if (func.getLogin().compareTo(login)==0) {
                    return func;
                }
            }
            return null;

        }
}
